步骤 11:添加导出配置¶
在 安装 与 测试
教程中,我们添加了 CMake 安装项目库和头文件的能力。在 打包 安装程序
教程中,我们添加了打包这些信息以便分发给他人的能力。
下一步是添加必要的信息,以便其他 CMake 项目可以使用我们的项目,无论它来自构建目录、本地安装还是打包。
第一步是更新我们的 install(TARGETS)
命令,不仅要指定 DESTINATION
,还要指定 EXPORT
。EXPORT
关键字生成一个 CMake 文件,其中包含从安装树导入 install 命令中列出的所有目标的代碼。因此,让我们继续显式 EXPORT
MathFunctions
库,方法是更新 MathFunctions/CMakeLists.txt
中的 install
命令,使其如下所示
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs}
EXPORT MathFunctionsTargets
DESTINATION lib)
# install include headers
install(FILES MathFunctions.h DESTINATION include)
现在我们已经导出了 MathFunctions
,我们还需要显式安装生成的 MathFunctionsTargets.cmake
文件。这可以通过将以下内容添加到顶层 CMakeLists.txt
的底部来完成
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
此时,您应该尝试运行 CMake。如果一切设置正确,您将看到 CMake 将生成如下错误
Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
path:
"/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
which is prefixed in the source directory.
CMake 告诉您,在生成导出信息期间,它将导出一个路径,该路径本质上与当前机器相关联,并且在其他机器上无效。 解决此问题的方法是更新 MathFunctions
的 target_include_directories()
,以了解当从构建目录以及安装/包中使用时,它需要不同的 INTERFACE
位置。 这意味着转换 MathFunctions
的 target_include_directories()
调用,使其如下所示
target_include_directories(MathFunctions
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
更新完成后,我们可以重新运行 CMake 并验证它不再发出警告。
此时,我们已经让 CMake 正确打包了所需的目标信息,但我们仍然需要生成一个 MathFunctionsConfig.cmake
,以便 CMake find_package()
命令可以找到我们的项目。 因此,让我们继续在项目的顶层添加一个名为 Config.cmake.in
的新文件,内容如下
@PACKAGE_INIT@
include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" )
然后,为了正确配置和安装该文件,将以下内容添加到顶层 CMakeLists.txt
的底部
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
include(CMakePackageConfigHelpers)
接下来,我们执行 configure_package_config_file()
。 此命令将配置提供的文件,但与标准的 configure_file()
方式略有不同。 为了正确使用此函数,除了所需的内容外,输入文件还应包含一行文本 @PACKAGE_INIT@
。 该变量将被替换为代码块,该代码块将设置的值转换为相对路径。 这些新值可以使用相同的名称引用,但前缀为 PACKAGE_
。
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
include(CMakePackageConfigHelpers)
# generate the config file that includes the exports
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
INSTALL_DESTINATION "lib/cmake/MathFunctions"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
接下来是 write_basic_package_version_file()
。 此命令写入一个文件,该文件由 find_package()
使用,记录所需软件包的版本和兼容性。 在这里,我们使用 Tutorial_VERSION_*
变量并声明它与 AnyNewerVersion
兼容,这表示此版本或任何更高版本与请求的版本兼容。
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
VERSION "${Tutorial_VERSION_MAJOR}.${Tutorial_VERSION_MINOR}"
COMPATIBILITY AnyNewerVersion
)
最后,设置安装这两个生成的文件
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake
DESTINATION lib/cmake/MathFunctions
)
此时,我们已经为我们的项目生成了一个可重定位的 CMake 配置,该配置可以在项目安装或打包后使用。 如果我们希望我们的项目也可以从构建目录中使用,我们只需将以下内容添加到顶层 CMakeLists.txt
的底部
export(EXPORT MathFunctionsTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake"
)
通过此导出调用,我们现在生成了一个 MathFunctionsTargets.cmake
,允许构建目录中配置的 MathFunctionsConfig.cmake
被其他项目使用,而无需安装它。